﻿using System.IO.Ports;
using System.Text;

namespace GCC.Container.Abstracts
{
    /// <summary>
    /// 抽象的串口通信服务
    /// </summary>
    /// <typeparam name="T">通信数据类型</typeparam>
    /// <remarks>注意,由于串口得特殊性,不关析构了服务还是client,双方都将被联合析构,想要停止只能析构</remarks>
    public abstract class AbsCommCOMServer<T> : AbsCommServer, IDisposable
    {
        /// <summary>
        /// 是否已经销毁
        /// </summary>
        protected bool _disposed;
        /// <summary>
        /// 取消token
        /// </summary>
        protected readonly CancellationTokenSource _cancellToken = new();

        /// <summary>
        /// 日志对象
        /// </summary>
        protected readonly AbsGCCLogger _logger;

        /// <summary>
        /// 是否运行中
        /// </summary>
        protected bool _running;


        /// <summary>
        /// server端对象
        /// </summary>
        protected AbsCommCOMClient<T> _comServer;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志模块实例</param>
        /// <param name="name">名称</param>
        public AbsCommCOMServer(string name, AbsGCCLogger logger)
        {
            ServerType = "COM";
            _logger = logger;
            Name = name;
            _comServer = GetServer(name);
            _comServer.OnDisposing += () =>
            {
                this.Dispose();
            };
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~AbsCommCOMServer()
        {
            Dispose(false);
        }

        /// <summary>
        /// 销毁模型
        /// </summary>
        /// <param name="flag">是否是用户主动调用</param>
        protected virtual void Dispose(bool flag)
        {
            if (_disposed)
            {
                return;
            }
            _disposed = true;


            try
            {
                if (_comServer != null)
                {
                    _comServer.Dispose();
                }
                _cancellToken.Cancel();
                _cancellToken.Dispose();
            }
            catch (Exception ex)
            {
                _logger.Error("AbsCommTcpClient dispose error.", exception: ex);
            }
        }

        /// <summary>
        /// 销毁模型
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }


        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="portName">端口名</param>
        /// <param name="baudRate">串行波特率</param>
        /// <param name="parity">奇偶校验检查协议。</param>
        /// <param name="dataBits">每个字节的标准数据位长度</param>
        /// <param name="stopBits">每个字节的标准停止位数</param>
        /// <param name="handshake">串行端口数据传输的握手协议</param>
        /// <param name="readTimeout">读取操作未完成时发生超时之前的毫秒数</param>
        /// <param name="writeTimeout">未完成时发生超时之前的毫秒数</param>
        /// <param name="isReadLineMode">是否是读行模式</param>
        /// <param name="encoding">如果是行模式,那么请给出编码</param>
        public AbsCommCOMClient<T>? Start(string portName,
            int? baudRate = null,
            Parity? parity = null,
            int? dataBits = null,
            StopBits? stopBits = null,
            Handshake? handshake = null,
            int? readTimeout = null,
            int? writeTimeout = null,
            bool? isReadLineMode = null,
            Encoding? encoding = null)
        {
            if (!_running)
            {
                lock (this)
                {
                    if (!_running)
                    {
                        _comServer.BindTo(
                            portName,
                            baudRate,
                            parity,
                            dataBits,
                            stopBits,
                            handshake,
                            readTimeout,
                            writeTimeout,
                            isReadLineMode,
                            encoding
                            );
                        if (!_comServer.Start())
                        {
                            return null;
                        }
                        _running = true;
                    }
                }
            }
            return _comServer;
        }



        /// <summary>
        /// 获取一个当前服务的客户端
        /// </summary>
        /// <param name="name">名称</param> 
        /// <returns></returns>
        protected abstract AbsCommCOMClient<T> GetServer(string name);
        /// <summary>
        /// 获取一个服务器专用客户端
        /// </summary>
        /// <param name="name">名称</param> 
        /// <returns></returns>
        protected abstract AbsCommCOMClient<T> GetServerClient(string name);
    }
}
